<template>
  <div class="app-container h-flex">
    <div v-loading="listLoading" class="tree-box app-container__left">
      <div class="type-title">菜单</div>
      <el-tree
        ref="tree_box"
        :data="menuTreeData"
        node-key="id"
        icon-class="el-icon-arrow-right"
        :expand-on-click-node="false"
        :props="defaultMenuProps"
        @node-click="nodeClick" />
    </div>
    <div ref="tree_box_right" class="h-flex-elastic v-flex overflow-hidden app-container__right">
      <filter-form :form="listQuery" :data="filterData" @search="search" @addForm="addForm" />
      <div ref="main" class="v-flex-elastic">
        <el-table
          v-if="height>0"
          ref="multipleTable"
          v-loading="listLoading"
          :data="tableData"
          border
          row-key="id"
          :height="height"
          style="width: 100%">
          <el-table-column label="序号" align="center" type="index" width="50" />
          <el-table-column prop="menuName" label="菜单名称" width="200" />
          <el-table-column prop="menuCode" show-overflow-tooltip label="菜单编号" />
          <el-table-column prop="menuPath" show-overflow-tooltip label="访问路径" />
          <el-table-column prop="menuFilePath" show-overflow-tooltip label="文件路径" />
          <el-table-column prop="orderNum" label="排序号" />
          <el-table-column label="按钮" min-width="170">
            <template slot-scope="{row}">
              {{ row.actions && row.actions.map(item => item.label).join(',') }}
            </template>
          </el-table-column>
          <el-table-column label="启用" align="center" width="70">
            <template slot-scope="{row, $index}">
              <el-switch v-model="row.status" :active-value="1" :inactive-value="0" @change="enable(row, $index)" />
            </template>
          </el-table-column>
          <el-table-column
            label="操作"
            fixed="right"
            align="center"
            width="120"
            class-name="small-padding fixed-width">
            <template slot-scope="{row ,$index}">
              <el-button
                v-permission-button="'ITPS-VIEW'"
                class="el-icon-defined"
                size="mini"
                icon="el-icon-view"
                @click="view(row)" />
              <el-button
                v-permission-button="'ITPS-UPDATE'"
                class="el-icon-defined"
                size="mini"
                icon="el-icon-edit"
                @click="updateForm(row,$index)" />
              <el-button
                v-permission-button="'ITPS-DELETE'"
                class="el-icon-defined"
                size="mini"
                icon="el-icon-delete"
                @click="deleteData(row,$index)" />
            </template>
          </el-table-column>
        </el-table>
      </div>

      <base-dialog
        class="menu-dialog"
        width="60%"
        :visible.sync="dialog.visible"
        :title="dialog.title"
        :loading="dialog.loading"
        :disabled="dialog.disabled"
        @open="beforeOpenDialog"
        @updateData="updateData">
        <el-form
          ref="dataForm"
          :rules="rules"
          :model="temp"
          :disabled="dialog.disabled"
          label-width="110px">
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="菜单名称" prop="menuName">
                <el-input v-model.trim="temp.menuName" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="菜单编号" prop="menuCode">
                <el-input v-if="dialog.title == '编辑'" v-model="temp.menuCode" disabled />
                <el-input v-else v-model.trim="temp.menuCode" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="所属应用" prop="appId">
                <select-tree
                  v-model="temp.appId"
                  :options="optionsApp"
                  :props="defaultProps"
                  :node-click="true"
                  @nodeClick="nodeAppClick" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="上级菜单" prop="parentId">
                <select-tree
                  ref="tree_box1"
                  v-model="temp.parentId"
                  :options="menuTreeDataApp"
                  :props="defaultProps" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="文件路径" prop="menuFilePath">
                <el-input v-model.trim="temp.menuFilePath" placeholder="路由component,相对views文件夹的路径" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="菜单路径" prop="menuPath">
                <el-input v-model.trim="temp.menuPath" placeholder="访问路径(路由或外部链接)" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="图标" prop="icon">
                <el-input v-model.trim="temp.icon" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="打开方式" prop="target">
                <el-select v-model="temp.target">
                  <el-option key="iframe" label="iframe" value="iframe" />
                  <el-option key="blank" label="blank" value="blank" />
                  <el-option key="expand" label="expand" value="expand" />
                  <el-option key="open" label="open" value="open" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="排序" prop="orderNum">
                <el-input v-model.number="temp.orderNum" />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item label="菜单按钮" prop="actions">
                <div class="action-tags">
                  <el-tag
                    v-for="(action, index) in temp.actions"
                    :key="action.value"
                    size="normal"
                    closable
                    @close="temp.actions.splice(index, 1)">
                    {{ action.label }}
                  </el-tag>
                  <el-popover
                    v-model="actionPopover"
                    popper-class="popper"
                    placement="right"
                    width="315"
                    trigger="click"
                    @show="showActionPopover">
                    <el-button slot="reference" class="action-tags-button" size="small">+ 添加权限</el-button>
                    <div class="action-tags-popover">
                      <p style="margin-bottom: 10px;font-weight: bold;">默认按钮</p>
                      <el-select v-model="defaultActions" multiple value-key="value">
                        <el-option v-for="(item, index) in optionsButton" :key="index" :value="item" :label="item.label">
                          <span style="float: left">{{ item.label }}</span>
                          <span style="float: right; color: #8492a6; font-size: 12px;margin-right: 15px;">{{ item.value }}</span>
                        </el-option>
                      </el-select>
                      <p style="margin: 10px 0;font-weight: bold;">自定义按钮</p>
                      <div class="action-tags-row">
                        <div class="action-tags-col" style="flex: 1;"><span style="color: red">*</span>按钮名称</div>
                        <div class="action-tags-col" style="flex: 1;"><span style="color: red">*</span>按钮编码</div>
                        <div v-if="dialogStatus!=='view'" class="action-tags-col" style="width: 20px">
                          <i class="el-icon-plus" @click="customActions.push({})" />
                        </div>
                      </div>
                      <div class="action-tags-rows">
                        <div v-for="(item, index) in customActions" :key="index" class="action-tags-row">
                          <template v-if="!optionsButton.find(child => child.value === item.value)">
                            <div class="action-tags-col" style="flex: 1;">
                              <el-input v-model="item.label" />
                            </div>
                            <div class="action-tags-col" style="flex: 1;">
                              <el-input v-model="item.value" />
                            </div>
                            <div v-if="dialogStatus!=='view'" class="action-tags-col" style="width: 20px">
                              <i class="el-icon-delete" @click="customActions.splice(index, 1)" />
                            </div>
                          </template>
                        </div>
                      </div>
                      <el-button style="width: 100%;margin-top: 15px;" type="primary" size="small" @click="changeAction">确定</el-button>
                    </div>
                  </el-popover>
                </div>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="24">
              <el-form-item
                label="菜单描述"
                prop="instructions">
                <el-input v-model="temp.instructions" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="启用">
                <el-switch v-model="temp.status" :active-value="1" :inactive-value="0" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="是否不展示在菜单" label-width="125px">
                <el-switch v-model="temp.properties.hidden" :active-value="1" :inactive-value="0" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="是否有过渡动画">
                <el-switch v-model="temp.properties.isTransition" :active-value="1" :inactive-value="0" />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="是否不展示在页签" label-width="125px">
                <el-switch v-model="temp.properties.isHiddenTag" :active-value="1" :inactive-value="0" />
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </base-dialog>
      <!-- <el-dialog
        width="60%"
        :title="textMap[dialogStatus]"
        :visible.sync="dialogFormVisible"
        :close-on-click-modal="false">
        <div slot="footer" class="dialog-footer">
          <el-button
            v-if="!disabled"
            type="primary"
            @click="dialogStatus==='create'?addData():updateData()">保存</el-button>
          <el-button @click="dialogFormVisible = false">取消</el-button>
        </div>
      </el-dialog> -->
    </div>
  </div>
</template>

<script>
import { getListApp } from '@/api/dsc/system/application'
import {
  getListTree,
  getList,
  saveOrUpdate,
  deleteById,
  getMenuByApp
} from '@/api/dsc/system/menu'
import { getListByTypeCode } from '@/api/dsc/system/dictionary/general'
import { tableMixin } from '@/utils/public'
export default {
  name: 'DscMenu',
  mixins: [tableMixin],
  data() {
    return {
      // 菜单树
      menuTreeData: [],
      menuTreeDataApp: [],
      defaultMenuProps: {
        children: 'children',
        label: 'label'
      },
      // 数据默认字段
      defaultProps: {
        parent: 'parentId', // 父级唯一标识
        value: 'id', // 唯一标识
        label: 'label', // 标签显示
        children: 'children' // 子级
      },
      // 所属应用数据列表
      optionsApp: [],
      // 菜单按钮下拉选项
      optionsButton: [],
      treeHeight: 0, // tree高度
      height: 0, // table高度
      tableData: [], // 表格数据
      listQuery: {
        // 搜索条件
        appId: '',
        pid: '',
        keyName: ''
      },
      filterData: {
        keyName: {
          key: 'keyName',
          type: 'input',
          placeholder: '请输入名称、编号'
        }
      },
      total: 0,
      textMap: {
        update: '编辑',
        view: '查看',
        create: '添加'
      },
      dialogFormVisible: false, // 弹窗开关
      dialogStatus: '', // 弹窗类型（添加、查看、编辑）
      dialog: {
        visible: false,
        title: '',
        loading: false,
        disabled: false
      },
      temp: {},
      tempForm: {
        // 弹窗表单
        id: '',
        menuName: '',
        menuCode: '',
        appId: '',
        parentId: '',
        menuFilePath: '',
        menuPath: '',
        target: 'iframe',
        instructions: '',
        orderNum: '',
        icon: '',
        actions: [],
        properties: {
          hidden: 0,
          isHiddenTag: 0,
          isTransition: 1
        },
        status: 1
      },
      rowIndex: null,
      rowObj: null, // 行数据
      rules: {},
      rulesModel: {
        menuName: [
          { required: true, message: '必填', trigger: 'blur' },
          { max: 20, message: '小于20个字符', trigger: 'blur' }
        ],
        menuCode: [
          { required: true, message: '必填', trigger: 'blur' },
          { max: 30, message: '小于30个字符', trigger: 'blur' }
        ],
        // menuFilePath: [{ required: true, message: '必填', trigger: 'blur' }, { max: 255, message: '小于255个字符', trigger: 'blur' }],
        menuPath: [
          { required: true, message: '必填', trigger: 'blur' },
          { max: 255, message: '小于255个字符', trigger: 'blur' }
        ],
        appId: [{ required: true, message: '必选', trigger: 'blur' }],
        target: [{ required: true, message: '必选', trigger: 'blur' }],
        orderNum: [
          { required: true, message: '必填', trigger: 'blur' },
          { type: 'number', message: '填写数字', trigger: 'blur' }
        ],
        instructions: [{ max: 255, message: '小于255个字符', trigger: 'blur' }]
      },
      listLoading: false,
      disabled: false, // 是否禁止表单操作
      multipleSelection: [], // 选择行的复选框
      defaultActions: [],
      customActions: [],
      actionPopover: false
    }
  },
  async created() {
    this.temp = Object.assign({}, this.tempForm)
    this.listLoading = true
    await this.getListTree()
    this.nodeClick(this.menuTreeData[0])
    this.$nextTick(_ => {
      this.$refs.tree_box && this.$refs.tree_box.setCurrentKey(this.listQuery.appId || this.listQuery.pid)
    })
    // 查询所属应用
    getListApp({}).then(response => {
      // 控制第一级平台不可选择
      for (const i of response.data) {
        i['disabled'] = true
      }
      this.optionsApp = response.data
    })
    // 查询菜单的按钮
    getListByTypeCode({ typeCode: this.publicConfig['SYS-BUTTON'] }).then(
      response => {
        // 默认选中 增删改查
        this.optionsButton = response.data.map(item => ({
          label: item.dicKey,
          value: item.dicValue
        }))
      }
    )
  },
  methods: {
    nodeAppClick(vue, node) {
      if (node.disabled) {
        return
      }
      this.temp.parentId = ''
      this.getMenuByApp(node.id)
    },
    // 通过应用查询菜单树
    getMenuByApp(id) {
      this.menuTreeDataApp = []
      getMenuByApp({ appId: id }).then(response => {
        this.menuTreeDataApp = response.data
        this.menuTreeDataApp[0].disabled = true
        this.setTreeDisable()
      })
    },
    setTreeDisable() {
      let data = [...this.menuTreeDataApp]
      let current = []
      while (data.length || current.length) {
        if (data[0] && data[0].id === this.temp.id) {
          this.$set(data[0], 'disabled', true)
          current = [...data[0].children]
          data = []
        } else {
          if (current.length) {
            this.$set(current[0], 'disabled', true)
            current.push(...current[0].children)
            current.shift()
          } else {
            data.push(...data[0].children)
            data.shift()
          }
        }
      }
    },
    // 查询菜单树
    getListTree() {
      return getListTree({}).then(response => {
        this.menuTreeData = response.data
      })
    },
    // 查询列表
    getList() {
      this.listLoading = true
      getList(this.listQuery).then(response => {
        this.tableData = response.data
        this.listLoading = false
      }).catch(() => {
        this.listLoading = false
      })
    },
    // 点击tree节点回调
    nodeClick(data) {
      this.listQuery.pid = data.id
      if (data.app) {
        this.listQuery.pid = ''
        this.listQuery.appId = data.id
      } else {
        this.listQuery.pid = data.id
        this.listQuery.appId = ''
      }
      this.search()
    },
    // 搜索
    search() {
      this.getList()
    },
    // 添加
    addForm() {
      if (this.listLoading) return
      this.menuTreeDataApp = []
      // this.disabled = false
      this.temp = Object.assign({}, this.tempForm)
      this.temp.actions = JSON.parse(JSON.stringify(this.optionsButton))
      // this.dialogStatus = 'create'
      // this.dialogFormVisible = true
      this.rules = Object.assign({}, this.rulesModel)
      this.dialog = Object.assign({}, this.dialog, {
        visible: true,
        title: '添加',
        loading: false,
        disabled: false
      })
    },
    // 添加数据
    // addData() {
    //   this.validate().then(() => {
    //     this.saveOrUpdate(this.temp, 1)
    //   })
    // },
    // 查看
    view(row) {
      // this.disabled = true
      this.temp = Object.assign({}, this.tempForm) // copy obj
      this.temp = Object.assign(this.temp, row) // copy obj
      if (!this.temp.properties) {
        this.$set(this.temp, 'properties', {
          hidden: 0,
          isHiddenTag: 0,
          isTransition: 1
        })
      }
      // this.removeActionId()
      if (this.temp.appId) this.getMenuByApp(this.temp.appId)
      // this.dialogStatus = 'view'
      this.rules = {}
      // this.dialogFormVisible = true
      this.dialog = Object.assign({}, this.dialog, {
        visible: true,
        title: '查看',
        loading: false,
        disabled: true
      })
    },
    // 针对按钮字典禁用了的按钮，在查出来的数据列表里面以status=0来删除该id
    // removeActionId() {
    //   this.temp.actionList.forEach((e, i) => {
    //     if (!e.status) {
    //       const index = this.temp.actionIds.indexOf(e.id)
    //       if (index > -1) {
    //         this.temp.actionIds.splice(index, 1)
    //       }
    //     }
    //   })
    // },
    // 编辑
    updateForm(row, $index) {
      // this.disabled = false
      this.rowIndex = $index
      this.rowObj = row
      this.temp = Object.assign({}, this.tempForm) // copy obj
      this.temp = Object.assign(this.temp, row) // copy obj
      this.temp.actions = this.temp.actions || []
      if (!this.temp.properties) {
        this.$set(this.temp, 'properties', {
          hidden: 0,
          isHiddenTag: 0,
          isTransition: 1
        })
      }
      // this.removeActionId()
      if (this.temp.appId) this.getMenuByApp(this.temp.appId)
      // this.dialogStatus = 'update'
      this.rules = Object.assign({}, this.rulesModel)
      // this.dialogFormVisible = true
      this.dialog = Object.assign({}, this.dialog, {
        visible: true,
        title: '编辑',
        loading: false,
        disabled: false
      })
    },
    // 编辑数据
    updateData() {
      this.validate().then(() => {
        this.saveOrUpdate(this.temp, 2)
      })
    },
    // type 1 添加，2 编辑
    saveOrUpdate(params, type) {
      const param = Object.assign({}, params)
      param.parentId = param.parentId || null
      saveOrUpdate(param).then(response => {
        if (this.dialog.title === '添加') {
          this.tableData.unshift(response.data)
          this.getListTree()
        } else {
          Object.assign(this.rowObj, response.data)
          // 左侧树编辑节点
          this.$refs.tree_box.getNode(response.data.id).data.label =
            response.data.menuName
          if (this.$refs.tree_box1) {
            this.$refs.tree_box1.updateNode(
              response.data.id,
              response.data.menuName
            )
          }
        }
        this.notifiySuccess('保存成功!')
        this.dialog.visible = false
      })
    },
    beforeOpenDialog() {
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    // 删除
    deleteData(row, $index) {
      this.confirmBox('确定删除?')
        .then(() => {
          deleteById(row.id).then(response => {
            this.notifiySuccess('删除成功!')
            this.search()
            this.$refs.tree_box.remove(row.id)
            if (this.$refs.tree_box1) this.$refs.tree_box1.removeNode(row.id)
          })
        })
        .catch(() => {})
    },
    // 启用、停用
    enable(row, $index) {
      this.rowObj = row
      this.rowIndex = $index
      this.saveOrUpdate(this.rowObj, 2)
    },
    showActionPopover() {
      this.defaultActions = this.temp.actions.filter(item => this.optionsButton.some(child => child.value === item.value))
      this.customActions = this.temp.actions.filter(item => !this.optionsButton.find(child => child.value === item.value))
    },
    changeAction() {
      const reg = /^ITPS-/
      const actions = [...this.defaultActions, ...this.customActions]
      if (this.customActions.some(item => !item.label || !item.value || !reg.test(item.value))) {
        this.notifiyError('按钮名称和编码不能为空,且必须以 “ITPS-” 开头')
        return
      }
      const obj = {}
      for (let i = 0, l = actions.length; i < l; i++) {
        if (obj[actions[i].value]) {
          this.notifiyError('不能有重复编码')
          return
        }
        obj[actions[i].value] = true
      }
      this.temp.actions = actions
      this.actionPopover = false
    },
    // 批量删除
    deleteBatch() {
      this.confirmBox('确定删除?')
        .then(() => {
          this.notifiySuccess('删除成功!')
          this.search()
        })
        .catch(() => {})
    },
    // 选择行复选框
    toggleSelection(rows) {
      if (rows) {
        rows.forEach(row => {
          this.$refs.multipleTable.toggleRowSelection(row)
        })
      } else {
        this.$refs.multipleTable.clearSelection()
      }
    },
    // 全选、反选
    handleSelectionChange(val) {
      this.multipleSelection = val
    }
  }
}
</script>

<style lang="scss" scoped>
.el-tag {
  margin-right: 5px;
}
.action-tags-rows{
  max-height: 200px;
  overflow: auto;
}
.action-tags-row{
  display: flex;
  align-items: center;
}
.action-tags-col{
  text-align: center;
  margin: 5px 5px 5px 0;
}
.el-icon-plus,
.el-icon-delete{
  cursor: pointer;
}
</style>

<style lang="scss">
.popper{
  .action-tags-rows{
    min-height: 100px;
  }
}
</style>
